package com.tinem.platform.web.auth.server.client;

import cn.hutool.core.util.ObjectUtil;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.module.starter.jpa.entity.client.ClientChannelDetails;
import com.tinem.platform.module.starter.jpa.entity.client.ClientChannelSecurity;
import com.tinem.platform.module.starter.jpa.repository.client.ClientChannelDetailsRepository;
import com.tinem.platform.module.starter.jpa.repository.client.ClientChannelSecurityRepository;
import com.tinem.platform.web.auth.page.PlatformClientDetails;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author fzh
 * @version v1
 * @program: platform
 * @className ClientDetailsServiceImpl
 * @description TODO
 * @site 
 * @company 
 * @create 2020-09-04 09:30
 */
@Service("platformClientDetailsService")
public class ClientDetailsServiceImpl implements ClientDetailsService {
    @Resource
    ClientChannelDetailsRepository clientChannelDetailsRepository;
    @Resource
    ClientChannelSecurityRepository clientChannelSecurityRepository;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        Optional<ClientChannelDetails> oauthClientDetailsOptional = clientChannelDetailsRepository.findById(clientId);
        if(!oauthClientDetailsOptional.isPresent()){
            throw new NoSuchClientException("No client with requested id: " + clientId);
        }
        ClientChannelDetails oauthClientDetails = oauthClientDetailsOptional.get();
        stringRedisTemplate.opsForHash().putAll(RedisKeyEnum.client_info.getKey(clientId),new HashMap<String,String>(){{
            put("clientId",ObjectUtil.defaultIfNull(oauthClientDetails.getClietId(),""));
            put("clientName",ObjectUtil.defaultIfNull(oauthClientDetails.getClientName(),""));
            put("resourceIds",ObjectUtil.defaultIfNull(oauthClientDetails.getResourceIds(),""));
            put("clientSecret",ObjectUtil.defaultIfNull(oauthClientDetails.getClientSecret(),""));
            put("scope",ObjectUtil.defaultIfNull(oauthClientDetails.getScope(),""));
            put("authorizedGrantTypes",ObjectUtil.defaultIfNull(oauthClientDetails.getAuthorizedGrantTypes(),""));
            put("webServerRedirectUri",ObjectUtil.defaultIfNull(oauthClientDetails.getWebServerRedirectUri(),""));
            put("authorities",ObjectUtil.defaultIfNull(oauthClientDetails.getAuthorities(),""));
            put("accessTokenValidity", oauthClientDetails.getAccessTokenValidity() == null ? "" : String.valueOf(oauthClientDetails.getAccessTokenValidity()));
            put("refreshTokenValidity",oauthClientDetails.getRefreshTokenValidity() == null ? "" : String.valueOf(oauthClientDetails.getRefreshTokenValidity()));
            put("additionalInformation",ObjectUtil.defaultIfNull(oauthClientDetails.getAdditionalInformation(),""));
            put("autoapprove",ObjectUtil.defaultIfNull(oauthClientDetails.getAutoapprove(),""));

            Optional<ClientChannelSecurity> clientChannelSecurityOptional = clientChannelSecurityRepository.findById(clientId);
            if(clientChannelSecurityOptional.isPresent()){
                ClientChannelSecurity clientChannelSecurity = clientChannelSecurityOptional.get();
                put("reqSign", ObjectUtil.defaultIfNull(String.valueOf(clientChannelSecurity.getReqSign()),""));
                put("reqSignType", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqSignType().name(),""));
                put("reqSignKey", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqSignKey(),""));
                put("resSign", ObjectUtil.defaultIfNull(String.valueOf(clientChannelSecurity.getResSign()),""));
                put("resSignType", ObjectUtil.defaultIfNull(clientChannelSecurity.getResSignType().name(),""));
                put("resSignKey", ObjectUtil.defaultIfNull(clientChannelSecurity.getResSignKey(),""));
                put("reqCrypto", ObjectUtil.defaultIfNull(String.valueOf(clientChannelSecurity.getReqCrypto()),""));
                put("reqCryptoType", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqCryptoType().name(),""));
                put("reqCryptoPuk", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqCryptoPuk(),""));
                put("reqCryptoKey", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqCryptoKey(),""));
                put("reqCryptoIv", ObjectUtil.defaultIfNull(clientChannelSecurity.getReqCryptoIv(),""));
                put("resCrypto", ObjectUtil.defaultIfNull(String.valueOf(clientChannelSecurity.getResCrypto()),""));
                put("resCryptoType", ObjectUtil.defaultIfNull(clientChannelSecurity.getResCryptoType().name(),""));
                put("resCryptoPpk", ObjectUtil.defaultIfNull(clientChannelSecurity.getResCryptoPpk(),""));
                put("resCryptoKey", ObjectUtil.defaultIfNull(clientChannelSecurity.getResCryptoKey(),""));
                put("resCryptoIv", ObjectUtil.defaultIfNull(clientChannelSecurity.getResCryptoIv(),""));
            }else{
                put("reqSign", String.valueOf(false));
                put("resSign", String.valueOf(false));
                put("reqCrypto", String.valueOf(false));
                put("resCrypto", String.valueOf(false));
            }
        }});
        stringRedisTemplate.expire(RedisKeyEnum.client_info.getKey(clientId),90, TimeUnit.DAYS);
        String channelScopeRedisKey = RedisKeyEnum.channel_scope.getKey(oauthClientDetails.getClietId());
        String[] jwtChannelScope = oauthClientDetails.getScope().split(",");
        stringRedisTemplate.opsForSet().add(
                channelScopeRedisKey
                , jwtChannelScope);
        stringRedisTemplate.expire(channelScopeRedisKey,90, TimeUnit.DAYS);
        return new PlatformClientDetails(oauthClientDetails);
    }
}
